/*
 * Copyright (c) 2005, 2014 vacoor
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 */
package org.vacoor.nothing.shop;

import org.vacoor.nothing.common.crypto.digest.Hash;
import org.vacoor.nothing.common.util.StringUtils;

import java.nio.charset.Charset;
import java.util.*;

/**
 * @author vacoor
 */
public class AlipayDirect {
    public static void main(String[] args) {
        final String ALIPAY_GATEWAY_NEW = "https://mapi.alipay.com/gateway.do?";
        final String SERVICE_NAME = "create_direct_pay_by_user";
        final String PAYMENT_TYPE = "1";
        String pid = "";
        String key = "";
        String charset = "utf-8";
        String signType = "MD5";

        //把请求参数打包成数组
        Map<String, String> sParaTemp = new HashMap<String, String>();
        sParaTemp.put("service", SERVICE_NAME);
        sParaTemp.put("partner", pid);
        sParaTemp.put("payment_type", PAYMENT_TYPE);
        sParaTemp.put("_input_charset", charset);
        sParaTemp.put("notify_url", "http://xxoo.xml");
        sParaTemp.put("return_url", "http://10.76.10.89:8080/return");
        sParaTemp.put("seller_email", "wayne@noahsgroup.com");  // 支付账户
        sParaTemp.put("out_trade_no", "2323");    // 订单号
        sParaTemp.put("subject", "火车票");
        sParaTemp.put("total_fee", "0.1");
        sParaTemp.put("hehe", "");
//		sParaTemp.put("body", body);
//        sParaTemp.put("show_url", show_url);
//        sParaTemp.put("anti_phishing_key", anti_phishing_key);
//        sParaTemp.put("exter_invoke_ip", exter_invoke_ip);

        // 清理空参数
        clean(sParaTemp);

        //
        //生成签名结果
        String paramSign = getParamsSign(signType, key, charset, sParaTemp);

        // 签名结果与签名方式加入请求提交参数组中
        sParaTemp.put("sign", paramSign);
        sParaTemp.put("sign_type", signType);

        StringBuilder buff = new StringBuilder();
        buff.append(ALIPAY_GATEWAY_NEW);
        buff.append(toNVString(sParaTemp));
        System.out.println(buff);
    }

    public static String getParamsSign(String signType, String key, String cs, Map<String, String> params) {
        String text = toSortedNVString(params);

        Charset charset = null == cs || "".equals(cs) ? Charset.defaultCharset() : Charset.forName(cs);
        if ("MD5".equals(signType)) {
            text += key;
            byte[] bytes = text.getBytes(charset);
            return new Hash.MD5(bytes).toHex();
        }
        return "";
    }

    /**
     * 按照自然顺序把数组所有元素排序，并按照“参数=参数值”的模式用“&”字符拼接成字符串
     *
     * @param params
     * @return
     */
    protected static String toSortedNVString(Map<String, String> params) {
        // 按照字典顺序
        return toSortedNVString(params, null);
    }

    /**
     * 把数组所有元素排序，并按照“参数=参数值”的模式用“&”字符拼接成字符串
     */
    protected static String toSortedNVString(Map<String, String> params, Comparator<String> comparator) {
        Map<String, String> sortedParams = new TreeMap<String, String>(comparator);
        sortedParams.putAll(params);
        return toNVString(sortedParams);
    }

    protected static String toNVString(Map<String, String> params) {
        StringBuilder buff = new StringBuilder();
        for (Map.Entry<String, String> param : params.entrySet()) {
            if (0 < buff.length()) {
                buff.append("&");
            }
            String name = param.getKey();
            String value = param.getValue();
            buff.append(null != name ? name : "").append("=").append(null != value ? value : "");
        }
        return buff.toString();
    }

    protected static Map<String, String> clean(Map<String, String> params) {
        List<String> needCleanKey = new ArrayList<String>();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            String name = entry.getKey();
            String value = entry.getValue();
            if (!StringUtils.hasText(name) || !StringUtils.hasText(value)) {
                needCleanKey.add(name);
            }
        }
        for (String key : needCleanKey) {
            params.remove(key);
        }
        return params;
    }
}
